package com.sz.biz.pay.account.service.impl;

import com.sz.biz.common.constants.ErrorCodes;
import com.sz.biz.common.constants.MessagesCodes;
import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.common.constants.ShortName;
import com.sz.biz.common.customer.entity.CusUser;
import com.sz.biz.common.customer.service.CustomerUserService;
import com.sz.biz.common.utils.NOGenerator;
import com.sz.biz.pay.account.dto.*;
import com.sz.biz.pay.account.entity.Account;
import com.sz.biz.pay.account.entity.ThirdPayAccount;
import com.sz.biz.pay.account.entity.Transaction;
import com.sz.biz.pay.account.service.AccountService;
import com.sz.biz.pay.account.service.BankCardService;
import com.sz.biz.pay.account.service.ThirdPayAccountService;
import com.sz.biz.pay.account.service.TransactionService;
import com.sz.biz.pay.constants.PayAction;
import com.sz.biz.pay.constants.PayConstant;
import com.sz.biz.pay.util.BackDataUtil;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.dto.ResultDto;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.i18n.I18nMessageHelper;
import com.sz.common.base.service.AbstractService;
import com.sz.common.base.utils.StringUtils;
import com.sz.common.base.utils.UUIDGenerator;
import com.sz.common.core.service.PrincipalLogUtils;
import com.sz.common.core.service.PrincipalUtils;
import com.sz.common.pay.common.DateGenerator;
import com.sz.common.pay.common.SequenceGenerator;
import com.sz.common.pay.pingan.constant.Constant;
import com.sz.common.pay.pingan.core.client.PAPay;
import com.sz.common.pay.pingan.entity.account.OpenAccountRequest;
import com.sz.common.pay.pingan.entity.account.OpenAccountResponse;
import com.sz.common.pay.pingan.entity.b2b.query.*;
import com.sz.common.pay.pingan.entity.query.BindAccountsResponse;
import com.sz.common.pay.pingan.entity.query.NumberAccountBalanceResponse;
import com.sz.common.pay.pingan.exception.NoAvailableConnectException;
import com.sz.common.pay.pingan.exception.OperationFailedException;
import com.sz.common.pay.pingan.exception.PayCommonException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;

/**
 * Function: TODO: ADD FUNCTION <br>
 * Author: siqishangshu <br>
 * Date: 2017-11-08 14:15:00
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class ThirdPayAccountServiceImpl extends AbstractService implements ThirdPayAccountService {

    @Autowired
    private AccountService accountService;

    @Autowired
    private TransactionService transactionService;

    @Autowired
    private BankCardService bankCardService;

    @Autowired
    CustomerUserService customerUserService;

    @Override
    public int insert(ThirdPayAccount entry) {
        valid(entry);
        return  dao.save(getMapperNamespace() + ShortName.INSERT, entry);
    }

    @Override
    public int delete(String id) {
        return 0;
    }

    @Override
    public int delete(List ids) {
        return 0;
    }

    @Override
    public int update(ThirdPayAccount entry) {
        dao.update(getSqlName("updateByPrimaryKeySelective"), entry);
        return 0;
    }

    @Override
    public ThirdPayAccount select(String id) {
        ThirdPayAccount thirdPayAccount = (ThirdPayAccount) dao.findForObject(getSqlName("selectByPrimaryKey"), id);
        return thirdPayAccount;
    }

    @Override
    public List<ThirdPayAccount> selectList(List ids) {
        return null;
    }

    @Override
    public List<ThirdPayAccount> selectAll() {
        return null;
    }

    @Override
    public QResultDto selectList(QueryParams param) {
        return null;
    }

    @Override
    public int count(QueryParams param) {
        return 0;
    }

    @Override
    public int countAll() {
        return 0;
    }

    @Override
    public void insertSelective(ThirdPayAccount thirdPayAccount) {
        valid(thirdPayAccount);
        dao.save(getSqlName("insertSelective"), thirdPayAccount);
    }


    @Override
    public void recharge(String id, double totalBalance, int TranscationType, double updateBalance, int AmountType) {
        BigDecimal totalBalanceBD = new BigDecimal(String.valueOf(totalBalance));
        BigDecimal updateBD = new BigDecimal(String.valueOf(updateBalance));
        if (StringUtils.isEmpty(id)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY, "id");
        }
        if (updateBalance <= 0) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "修改金额大于0");
        }
        List<Account> accounts = accountService.findByAccountType(PayConstant.AccountType.LOGISTICS_PLATFORM);
        if (null == accounts || accounts.isEmpty()) {
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_ACCOUNT_NOT_EXISTS);
        }
        Account systemAccount = accounts.get(0);
        Transaction transaction = new Transaction();
        transaction.setId(NOGenerator.getTranNo(TranscationType));
        transaction.setTranType(TranscationType);
        transaction.setThirdLogNo(SequenceGenerator.getThirdLogNo());

        transaction.setIsDeleted(false);
        ThirdPayAccount thirdPayAccount = select(id);

        BigDecimal queryTotalBalance = new BigDecimal(String.valueOf(thirdPayAccount.getTotalBalance()));
        BigDecimal queryTotalAmount = new BigDecimal(String.valueOf(thirdPayAccount.getTotalAmount()));
        BigDecimal queryTotalFreezeAmount = new BigDecimal(String.valueOf(thirdPayAccount.getTotalFreezeAmount()));
        transaction.setThirdType(thirdPayAccount.getThirdType());
        transaction.setCreateUserId(PrincipalUtils.getAccountId());
        transaction.setCurrency(thirdPayAccount.getCurrency());
        transaction.setTranDate(DateGenerator.getyyyyMMdd());
        transaction.setTranTime(DateGenerator.getHHmmss());
        transaction.setTranAmount(updateBalance);
        transaction.setCreateTime(new Date());

        if (updateBalance < 0) {
            transaction.setTranStatus(1);
            transaction.setNote("修改金额不能存在负值");
            transactionService.insert(transaction);
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_CHANGE_AMOUNT_NOT_NEGATIVE);
        }
        if (TranscationType == PayConstant.TranscationType.RECHARGE) {
            transaction.setInAccountId(thirdPayAccount.getAccountId());
            transaction.setInThirdPayAccountId(thirdPayAccount.getThirdPayId());
            transaction.setInAccountBalance(thirdPayAccount.getTotalBalance());
            transaction.setOutAccountId(systemAccount.getId());

            if (AmountType == PayConstant.AmountType.FREEZEBALANCE) {
                if (totalBalanceBD.compareTo(queryTotalBalance.add(updateBD)) == 0) {
                    thirdPayAccount.setTotalBalance(totalBalanceBD.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                    thirdPayAccount.setTotalFreezeAmount(queryTotalFreezeAmount.add(updateBD).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                } else {
                    transaction.setTranStatus(1);
                    transaction.setNote("金额存在问题");
                    transactionService.insert(transaction);
                    throw Exceptions.bizException(ErrorCodes.ERROR_PAY_TOTALBALANCE_ERROR);
                }
            } else {
                if (totalBalanceBD.compareTo(queryTotalBalance.add(updateBD)) == 0) {
                    thirdPayAccount.setTotalBalance(totalBalanceBD.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                    thirdPayAccount.setTotalAmount(queryTotalAmount.add(updateBD).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                } else {
                    transaction.setTranStatus(1);
                    transaction.setNote("金额存在问题");
                    transactionService.insert(transaction);
                    throw Exceptions.bizException(ErrorCodes.ERROR_PAY_TOTALBALANCE_ERROR);
                }
            }
        }

        if (TranscationType == PayConstant.TranscationType.DECREASE) {
            transaction.setOutAccountId(thirdPayAccount.getAccountId());
            transaction.setOutThirdPayAccountId(thirdPayAccount.getThirdPayId());
            transaction.setOutAccountBalance(thirdPayAccount.getTotalBalance());
            transaction.setInAccountId(systemAccount.getId());
            transaction.setInAccountBalance(updateBalance);

            if (AmountType == PayConstant.AmountType.FREEZEBALANCE) {
                if (totalBalanceBD.compareTo(queryTotalBalance.subtract(updateBD)) == 0) {
                    if (queryTotalFreezeAmount.compareTo(updateBD) == -1) {
                        transaction.setTranStatus(1);
                        transaction.setNote("冻结余额不足");
                        transactionService.insert(transaction);
                        throw Exceptions.bizException(ErrorCodes.ERROR_PAY_BALANCE_LACK);
                    }
                    thirdPayAccount.setTotalBalance(totalBalanceBD.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                    thirdPayAccount.setTotalFreezeAmount(queryTotalFreezeAmount.add(updateBD).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                } else {
                    transaction.setTranStatus(1);
                    transaction.setNote("冻结金额存在问题");
                    transactionService.insert(transaction);
                    throw Exceptions.bizException(ErrorCodes.ERROR_PAY_TOTALBALANCE_ERROR);
                }
            } else {
                if (totalBalanceBD.compareTo(queryTotalBalance.subtract(updateBD)) == 0) {
                    if (queryTotalAmount.compareTo(updateBD) == -1) {
                        transaction.setTranStatus(1);
                        transaction.setNote("金额不足");
                        transactionService.insert(transaction);
                        throw Exceptions.bizException(ErrorCodes.ERROR_PAY_FREEZE_AMOUNT_LACK);
                    }
                    thirdPayAccount.setTotalBalance(totalBalanceBD.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                    thirdPayAccount.setTotalAmount(queryTotalAmount.subtract(updateBD).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                } else {
                    transaction.setTranStatus(1);
                    transaction.setNote("金额存在问题");
                    transactionService.insert(transaction);
                    throw Exceptions.bizException(ErrorCodes.ERROR_PAY_TOTALBALANCE_ERROR);
                }
            }
        }

        transaction.setTranStatus(0);
        transaction.setNote("系统交易");
        update(thirdPayAccount);
        transactionService.insert(transaction);
    }

    /**
     * 根据账户ID和第三方类型查询第三方账户
     *
     * @param accountId 账户ID
     * @param thirdType 第三方类型
     * @return
     */
    @Override
    public ThirdPayAccount findByAccountIdAndThirdType(String accountId, String thirdType) {
        ParamData pd = new ParamData();
        pd.put("accountId", accountId);
        pd.put("thirdType", thirdType);
        return (ThirdPayAccount) dao.findForObject(getSqlName("selectByAccountIdAndThirdType"), pd);
    }

    @Override
    public ThirdPayAccount getByAccountIdAndThirdType(String accountId, String thirdType) {
        ParamData pd = new ParamData();
        pd.put("accountId", accountId);
        pd.put("thirdType", thirdType);
        return (ThirdPayAccount) dao.findForObject(getSqlName("findByAccountIdAndThirdType"), pd);
    }


    @Override
    public String findThirdPayId(String id) {
        if (StringUtils.isEmpty(id)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY, "id");
        }
        return (String) dao.findForObject(getSqlName("selectThirdPayIdByUserName"), id);
    }

    /**
     * 查询第三方账户的相关信息
     *
     * @param thirdType 第三方账户类型
     * @return
     */
    @Override
    public ResultDto findAccountInfo(String thirdType) {
        ResultDto resultDto = new ResultDto();
        List<AccountInfoShortDto> accountInfoShortDtos = new ArrayList<>();
        //查询所有平台账户
        List<Account> accounts = accountService.findByAccountType(PayConstant.AccountType.PLATFORM);
        for (Account account : accounts) {
            AccountInfoShortDto accountInfoShortDto = new AccountInfoShortDto();
            String custName = account.getCustName();//会员名称
            //根据账户ID和第三方会员支付类型查找第三方账户
            ThirdPayAccount thirdPayAccount = this.findByAccountIdAndThirdType(account.getId(), thirdType);
            if (null == thirdPayAccount) {
                accountInfoShortDto.setAccountId(account.getId());
                accountInfoShortDto.setCustName(custName);
                accountInfoShortDto.setCustomerId(account.getCustomerId());
                accountInfoShortDto.setOpenAccount(false);
                accountInfoShortDtos.add(accountInfoShortDto);
            } else {
                String thirdPayId = thirdPayAccount.getThirdPayId();//子账户账号

                ResultDto bindAccountsResultDto = bankCardService.queryAccountCard(thirdPayId);
                ResultDto numberAccountBalanceResultDto = bankCardService.queryAccountBalance(thirdPayId);

                if (!(bindAccountsResultDto.getData() instanceof BindAccountsResponse)) {
                    return bindAccountsResultDto;
                }
                if (!(numberAccountBalanceResultDto.getData() instanceof NumberAccountBalanceResponse)) {
                    return numberAccountBalanceResultDto;
                }

                if (bindAccountsResultDto.getData() instanceof BindAccountsResponse
                        && numberAccountBalanceResultDto.getData() instanceof NumberAccountBalanceResponse
                        ) {
                    //会员绑定信息查询
                    BindAccountsResponse bindAccountsResponse = (BindAccountsResponse) bindAccountsResultDto.getData();

                    //查询会员子账户余额
                    NumberAccountBalanceResponse numberAccountBalanceResponse = (NumberAccountBalanceResponse) numberAccountBalanceResultDto.getData();
                    String totalCount = bindAccountsResponse.getTotalCount();
                    if ("1".equals(bindAccountsResponse.getTotalCount())) {
                        int count = bankCardService.getCardNum(thirdPayAccount.getId());
                        totalCount = String.valueOf(count);
                    }
                    accountInfoShortDto.setCustName(custName);
                    accountInfoShortDto.setCustomerId(account.getCustomerId());
                    accountInfoShortDto.setTotalBalance(unitConversion(numberAccountBalanceResponse.getTotalBalance()));
                    accountInfoShortDto.setTotalCount(totalCount);
                    accountInfoShortDto.setCurrency(thirdPayAccount.getCurrency());
                    accountInfoShortDto.setThirdPayAccountId(thirdPayAccount.getId());
                    accountInfoShortDto.setAccountId(account.getId());
                    accountInfoShortDto.setOpenAccount(true);
                    accountInfoShortDtos.add(accountInfoShortDto);

                }


            }
        }
        resultDto.setData(accountInfoShortDtos);
        return resultDto;
    }

    @Override
    public ResultDto findAccountBalance(String thirdPayAccountId) {
        ThirdPayAccount thirdPayAccount = this.findById(thirdPayAccountId);
        if (null == thirdPayAccount) {
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_THIRDACCOUNT_NOT_EXISTS);
        }
        Account account = accountService.findAccountById(thirdPayAccount.getAccountId());
        if (null == account) {
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_ACCOUNT_NOT_EXISTS);
        }
        AccountBalanceDto accountBalanceDto = new AccountBalanceDto();
        //查询余额信息
        ResultDto result = bankCardService.queryAccountBalance(thirdPayAccount.getThirdPayId());
        if (result.getData() instanceof NumberAccountBalanceResponse) {
            NumberAccountBalanceResponse numberAccountBalanceResponse = (NumberAccountBalanceResponse) result.getData();
            accountBalanceDto.setAccountId(account.getId());
            accountBalanceDto.setTotalBalance(unitConversion(numberAccountBalanceResponse.getTotalBalance()));
            accountBalanceDto.setFreezeAmount(unitConversion(numberAccountBalanceResponse.getTotalFreezeAmount()));
            String availableBalance = String.valueOf(Double.parseDouble(numberAccountBalanceResponse.getTotalBalance()) - Double.parseDouble(numberAccountBalanceResponse.getTotalFreezeAmount()));
            accountBalanceDto.setAvailableBalance(unitConversion(availableBalance));
            accountBalanceDto.setCurrency(thirdPayAccount.getCurrency());
            accountBalanceDto.setCustAcctId(thirdPayAccount.getThirdPayId());
            accountBalanceDto.setThirdCustId(thirdPayAccount.getAccountId());
            result.setData(accountBalanceDto);
        }

        return result;
    }

    @Override
    public ThirdPayAccount findById(String id) {
        if (StringUtils.isEmpty(id)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY, "id");
        }
        return (ThirdPayAccount) dao.findForObject(getSqlName("findById"), id);
    }

    /**
     * 会员子账户开立请求
     *
     * @param accountId
     * @return
     */
    @Override
    public ResultDto openAccountRequest(String accountId) {
        ResultDto resultDto = new ResultDto();
        //根据id查询账户
        Account account = accountService.findAccountById(accountId);

        String thirdLogNo = SequenceGenerator.getThirdLogNo();
        OpenAccountRequest openAccountRequest = new OpenAccountRequest();
        openAccountRequest.setSupAcctId(Constant.SUP_ACCT_ID); //资金汇总账号
        openAccountRequest.setFuncFlag(PayConstant.OpenAccountFlag.OPEN); //功能标志1：开户
        openAccountRequest.setThirdCustId(accountId); //电商平台会员ID
        openAccountRequest.setCustProperty(PayConstant.MemberProperties.DEF);           //会员属性
        openAccountRequest.setNickName(account.getNickName());            //会员昵称
        openAccountRequest.setMobilePhone(account.getMobilePhone());  //手机号码
        openAccountRequest.setEmail(account.getEmail());                   //邮箱
        openAccountRequest.setReserve(account.getReserve());
        OpenAccountResponse openAccountResponse = null;

        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PAY, UserActions.REQUEST, PayAction.OPENACCOUNT,
                makeBackData(thirdLogNo, openAccountRequest));
        Object object = null;
        try {
            openAccountResponse = (OpenAccountResponse)
                    PAPay.sendMessage(thirdLogNo, openAccountRequest, OpenAccountResponse.class);
            resultDto.setData(openAccountResponse);
            resultDto.setMsg(I18nMessageHelper.getI18nMessage(MessagesCodes.MODULE_PAY_ACCOUNT_OPEN_SUCCESS, null));
            object = openAccountResponse;
        } catch (NoAvailableConnectException e) {

            object = e.getMessage();
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_AVAILABLE_CONNECT);
        } catch (OperationFailedException e) {

            object = e.getErrorMessage();
            resultDto.setErrorCode(ErrorCodes.ERROR_PAY_OPERATION.getCode());
            resultDto.setMsg(e.getErrorMessage().getRspCode() + " " + e.getErrorMessage().getRspMsg());
            resultDto.setData(e.getErrorMessage());
        } catch (PayCommonException e) {
            object = e.getMessage();
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_COMMON);

        } finally {

            PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PAY, UserActions.RESPONSE, PayAction.OPENACCOUNT,
                    makeBackData(thirdLogNo, object));

        }
        return resultDto;
    }

    /**
     * 开户
     *
     * @param accountId 账户ID
     * @return
     */
    @Override
    public ResultDto openAccount(String accountId) {

        ResultDto resultDto = this.openAccountRequest(accountId);
        if (resultDto.getData() instanceof OpenAccountResponse) {
            OpenAccountResponse openAccountResponse = (OpenAccountResponse) resultDto.getData();
            Account account = accountService.findAccountById(accountId);
            //保存第三方账户信息
            ThirdPayAccount thirdPayAccount = new ThirdPayAccount();
            thirdPayAccount.setId(UUIDGenerator.generateRandomUUID());
            thirdPayAccount.setAccountId(accountId);
            thirdPayAccount.setThirdPayId(openAccountResponse.getCustAcctId());
            thirdPayAccount.setThirdType(PayConstant.PaymentType.PINGAN);
            thirdPayAccount.setThirdPayName(account.getCustName());
            thirdPayAccount.setCurrency(PayConstant.Currency.CNY);
            this.insertSelective(thirdPayAccount);
            resultDto.setData(true);
        }
        return resultDto;
    }

    @Override
    public ThirdPayAccount findByCustAcctId(String thirdPayId) {
        return (ThirdPayAccount) dao.findForObject(getSqlName("findByPACustAcctId"), thirdPayId);
    }

    /**
     * 根据系统登录用户查找账户ID
     *
     * @return
     */
    @Override
    public String findAccountId() {
        CusUser cusUser = customerUserService.findById(PrincipalUtils.getAccountId());
        Account account = accountService.findAccountByCustomerId(cusUser.getRefCustomerId());
        if (null == account) {
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_ACCOUNT_NOT_EXISTS);
        }
        return account.getId();
    }

    /**
     * 根据系统登录用户查找账户
     * @return
     */
    @Override
    public Account findAccount() {
        CusUser cusUser = customerUserService.findById(PrincipalUtils.getAccountId());
        return accountService.findAccountByCustomerId(cusUser.getRefCustomerId());
    }

    /**
     * 根据系统登录用户查找第三方账户ID
     *
     * @param thirdType
     * @return
     */
    @Override
    public String findThirdPayAccountId(String thirdType) {
        ThirdPayAccount thirdPayAccount = this.findByAccountIdAndThirdType(findAccountId(), thirdType);
        if (null == thirdPayAccount) {
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_THIRDACCOUNT_NOT_EXISTS);
        }
        return thirdPayAccount.getId();
    }

    @Override
    public ThirdPayAccount findThirdPayAccount(String thirdType) {
        return this.findByAccountIdAndThirdType(findAccountId(),thirdType);
    }

    @Override
    public void changeDeleteSign(ThirdPayAccount thirdPayAccount) {
        dao.update(getSqlName("changeDeleteSign"),thirdPayAccount);
    }

    //TODO
    @Override
    public ResultDto getMemberBalance(String thirdPayAccountId) {
        ResultDto resultDto = new ResultDto();
        ThirdPayAccount thirdPayAccount = this.findById(thirdPayAccountId);
        if(null == thirdPayAccount){
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_THIRDACCOUNT_NOT_EXISTS);
        }
        String thirdLogNo = SequenceGenerator.getThirdLogNo();
        MemberFundsAccountBalanceRequest memberFundsAccountBalanceRequest = new MemberFundsAccountBalanceRequest();
        memberFundsAccountBalanceRequest.setCustAcctId(thirdPayAccount.getThirdPayId());
        memberFundsAccountBalanceRequest.setThirdCustId(thirdPayAccount.getAccountId());
        memberFundsAccountBalanceRequest.setPageNum("1");
        memberFundsAccountBalanceRequest.setSupAcctId(Constant.SUP_ACCT_ID);
        memberFundsAccountBalanceRequest.setSelectFlag("1");

        MemberFundsAccountBalanceResponse memberFundsAccountBalanceResponse = null;
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PAY, UserActions.REQUEST, PayAction.QUERYBALANCE,
                makeBackData(thirdLogNo, memberFundsAccountBalanceRequest));
        Object object = null;
        try {
            memberFundsAccountBalanceResponse = (MemberFundsAccountBalanceResponse)
                    PAPay.sendMessage(thirdLogNo,memberFundsAccountBalanceRequest, MemberFundsAccountBalanceResponse.class);
            object = memberFundsAccountBalanceResponse;

                MemberFundsAccountBalanceDto memberFundsAccountBalanceDto = new MemberFundsAccountBalanceDto();
                memberFundsAccountBalanceDto.setCustAcctId(memberFundsAccountBalanceResponse.getCustAcctId()[0]);
                memberFundsAccountBalanceDto.setCustFlag(memberFundsAccountBalanceResponse.getCustFlag()[0]);
                memberFundsAccountBalanceDto.setCustType(memberFundsAccountBalanceResponse.getCustType()[0]);
                memberFundsAccountBalanceDto.setCustStatus(memberFundsAccountBalanceResponse.getCustStatus()[0]);
                memberFundsAccountBalanceDto.setThirdCustId(memberFundsAccountBalanceResponse.getThirdCustId()[0]);
                memberFundsAccountBalanceDto.setMainAcctId(memberFundsAccountBalanceResponse.getMainAcctId()[0]);
                memberFundsAccountBalanceDto.setCustName(memberFundsAccountBalanceResponse.getCustName()[0]);
                memberFundsAccountBalanceDto.setTotalAmount(this.unitConversion(memberFundsAccountBalanceResponse.getTotalAmount()[0]));
                memberFundsAccountBalanceDto.setTotalBalance(this.unitConversion(memberFundsAccountBalanceResponse.getTotalBalance()[0]));
                memberFundsAccountBalanceDto.setTotalFreezeAmount(this.unitConversion(memberFundsAccountBalanceResponse.getTotalFreezeAmount()[0]));
                memberFundsAccountBalanceDto.setTranDate(memberFundsAccountBalanceResponse.getTranDate()[0]);

            resultDto.setData(memberFundsAccountBalanceDto);
        } catch (NoAvailableConnectException e) {
            object = e.getMessage();
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_AVAILABLE_CONNECT);
        } catch (OperationFailedException e) {
            object = e.getErrorMessage();
            resultDto.setErrorCode(ErrorCodes.ERROR_PAY_OPERATION.getCode());
            resultDto.setMsg(e.getErrorMessage().getRspCode()+" "+ e.getErrorMessage().getRspMsg());
            resultDto.setData(Boolean.FALSE);
        } catch (PayCommonException e) {
            object = e.getErrorMessage();
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_COMMON);
        }finally {
            PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PAY, UserActions.RESPONSE, PayAction.QUERYBALANCE,
                    BackDataUtil.makeMap(thirdLogNo, object));
        }
        return resultDto;
    }

    @Override
    public ResultDto findOpenRemoveAccountDetails(TimePeriodOpenRemoveAccountDetailsRequest timePeriodOpenRemoveAccountDetailsRequest) {
        ResultDto resultDto = new ResultDto();
        String thirdLogNo = SequenceGenerator.getThirdLogNo();
        timePeriodOpenRemoveAccountDetailsRequest.setSupAcctId(Constant.SUP_ACCT_ID);
        timePeriodOpenRemoveAccountDetailsRequest.setBeginDate("20171227");
        timePeriodOpenRemoveAccountDetailsRequest.setEndDate("20180105");
        timePeriodOpenRemoveAccountDetailsRequest.setPageNum("1");
        TimePeriodOpenRemoveAccountDetailsResponse timePeriodOpenRemoveAccountDetailsResponse = null;
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PAY, UserActions.REQUEST, PayAction.OPENREMOVEACCOUNT,
                makeBackData(thirdLogNo, timePeriodOpenRemoveAccountDetailsRequest));
        Object object = null;
        try {
            timePeriodOpenRemoveAccountDetailsResponse = (TimePeriodOpenRemoveAccountDetailsResponse)
                    PAPay.sendMessage(thirdLogNo,timePeriodOpenRemoveAccountDetailsRequest, TimePeriodOpenRemoveAccountDetailsResponse.class);
            object = timePeriodOpenRemoveAccountDetailsResponse;
            List<TimePeriodOpenRemoveAccountDetailsDto> timePeriodOpenRemoveAccountDetailsDtos = new ArrayList<>();
            for (int i = 0; i < Integer.parseInt(timePeriodOpenRemoveAccountDetailsResponse.getRecordNum()); i++) {
                TimePeriodOpenRemoveAccountDetailsDto timePeriodOpenRemoveAccountDetailsDto = new TimePeriodOpenRemoveAccountDetailsDto();
                timePeriodOpenRemoveAccountDetailsDto.setFrontLogNo(timePeriodOpenRemoveAccountDetailsResponse.getFrontLogNo()[i]);
                timePeriodOpenRemoveAccountDetailsDto.setUserStatus(timePeriodOpenRemoveAccountDetailsResponse.getUserStatus()[i]);
                timePeriodOpenRemoveAccountDetailsDto.setCustAcctId(timePeriodOpenRemoveAccountDetailsResponse.getCustAcctId()[i]);
                timePeriodOpenRemoveAccountDetailsDto.setCustFlag(timePeriodOpenRemoveAccountDetailsResponse.getCustFlag()[i]);
                timePeriodOpenRemoveAccountDetailsDto.setCustName(timePeriodOpenRemoveAccountDetailsResponse.getCustName()[i]);
                timePeriodOpenRemoveAccountDetailsDto.setThirdCustId(timePeriodOpenRemoveAccountDetailsResponse.getThirdCustId()[i]);
                timePeriodOpenRemoveAccountDetailsDto.setTranDate(timePeriodOpenRemoveAccountDetailsResponse.getTranDate()[i]);
                timePeriodOpenRemoveAccountDetailsDto.setCounterId(timePeriodOpenRemoveAccountDetailsResponse.getCounterId()[i]);
                timePeriodOpenRemoveAccountDetailsDtos.add(timePeriodOpenRemoveAccountDetailsDto);
            }


            resultDto.setData(timePeriodOpenRemoveAccountDetailsDtos);
        } catch (NoAvailableConnectException e) {
            object = e.getMessage();
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_AVAILABLE_CONNECT);
        } catch (OperationFailedException e) {
            object = e.getErrorMessage();
            resultDto.setErrorCode(ErrorCodes.ERROR_PAY_OPERATION.getCode());
            resultDto.setMsg(e.getErrorMessage().getRspCode()+" "+ e.getErrorMessage().getRspMsg());
            resultDto.setData(Boolean.FALSE);
        } catch (PayCommonException e) {
            object = e.getErrorMessage();
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_COMMON);
        }finally {
            PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_PAY, UserActions.RESPONSE, PayAction.OPENREMOVEACCOUNT,
                    BackDataUtil.makeMap(thirdLogNo, object));
        }
        return resultDto;
    }


    //TODO
    @Override
    public String getBalance(String thirdPayAccountId) {
        String totalAmount = null;
        ResultDto resultDto = this.getMemberBalance(thirdPayAccountId);
        if(resultDto.getData() instanceof MemberFundsAccountBalanceDto){
            totalAmount = ((MemberFundsAccountBalanceDto) resultDto.getData()).getTotalAmount();
        }
        return totalAmount;
    }

    //TODO
    @Override
    public ResultDto findAccountBaseInfo(String thirdType) {
        ResultDto resultDto = new ResultDto();
        //查询所有平台账户
        List<Account> accounts = accountService.findByAccountType(PayConstant.AccountType.PLATFORM);
        if(accounts.isEmpty()){
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_ACCOUNT_NOT_EXISTS);
        }
        List<AccountBaseInfoDto> accountBaseInfoDtoList = new ArrayList<>();
        for (Account account:accounts
             ) {
            AccountBaseInfoDto accountBaseInfoDto = new AccountBaseInfoDto();
            ThirdPayAccount thirdPayAccount = this.findByAccountIdAndThirdType(account.getId(),thirdType);
            if(null == thirdPayAccount){
                accountBaseInfoDto.setCustName(account.getCustName());
                accountBaseInfoDto.setSigning(false);

            }else {
                accountBaseInfoDto.setCustName(account.getCustName());
                accountBaseInfoDto.setTotalAmount(this.getBalance(thirdPayAccount.getId()));
                accountBaseInfoDto.setAccountId(account.getId());
                accountBaseInfoDto.setSigning(true);
            }
            accountBaseInfoDtoList.add(accountBaseInfoDto);

        }
        resultDto.setData(accountBaseInfoDtoList);
        return resultDto;
    }

    //TODO
    @Override
    public ResultDto findAccountBaseInfo() {
        ResultDto resultDto = new ResultDto();
        Account account = this.findAccount();
        if (null == account){
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_ACCOUNT_NOT_EXISTS);
        }
        ThirdPayAccount thirdPayAccount = this.findThirdPayAccount(PayConstant.PaymentType.PINGAN);
        if (null == thirdPayAccount){
            throw Exceptions.bizException(ErrorCodes.ERROR_PAY_THIRDACCOUNT_NOT_EXISTS);
        }
        AccountBaseInfoDto accountBaseInfoDto = new AccountBaseInfoDto();
        accountBaseInfoDto.setCustName(account.getCustName());
        accountBaseInfoDto.setTotalAmount(this.getBalance(thirdPayAccount.getId()));
        accountBaseInfoDto.setAccountId(account.getId());
        resultDto.setData(accountBaseInfoDto);
        return resultDto;
    }


    void valid(ThirdPayAccount thirdPayAccount) {
        if (thirdPayAccount != null) {
            if (StringUtils.isEmpty(thirdPayAccount.getId())) {
                throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY, "id");
            }
            if (StringUtils.isEmpty(thirdPayAccount.getAccountId())) {
                throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY, "accountId");
            }
            if (StringUtils.isEmpty(thirdPayAccount.getThirdPayId())) {
                throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY, "thirdPayId");
            }
        }
    }

    @Override
    protected String getMapperNamespace() {
        return "com.sz.biz.pay.account.ThirdPayAccountMapper";
    }

    private void sysLogisticsChargeTransaction(String thirdAccountId, String tranType) {

    }

    private String unitConversion(String balance) {
        DecimalFormat df = new DecimalFormat(PayConstant.UnitConversion.PERCENTILE);
        double dBalance = Double.valueOf(balance);
        if (dBalance > PayConstant.UnitConversion.BILLION) {
            dBalance = dBalance / PayConstant.UnitConversion.BILLION;
            return String.valueOf(df.format(dBalance)) + PayConstant.RmbUnit.BILLION;
        } else if (dBalance > PayConstant.UnitConversion.MILLION) {
            dBalance = dBalance / PayConstant.UnitConversion.MILLION;
            return String.valueOf(df.format(dBalance)) + PayConstant.RmbUnit.MILLION;
        } else {
            return String.valueOf(df.format(dBalance)) + PayConstant.RmbUnit.YUAN;
        }
    }

    private Map makeBackData(String thirdLogNo, Object obj) {
        Map map = new HashMap<>(16);
        map.put("thirdLogNo", thirdLogNo);
        map.put(obj.getClass().getSimpleName(), obj);

        return map;
    }


}
